package demo1;

import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Scalar;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 86185
 * Date: 2023-04-07
 * Time: 19:10
 */
public class GrayNonlinearTrans {
    static {
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
    }
    /**
     * 伽马校正
     * 伽马校正对图像的修正作用就是通过增强低灰度或高灰度的细节实现的
     * 值越小，对图像低灰度部分的扩展作用就越强，值越大，对图像高灰度部分的扩展作用就越强，
     * 通过不同的值，就可以达到增强低灰度或高灰度部分细节的作用。
     * 在对图像进行伽马变换时，如果输入的图像矩阵是CV_8U,在进行幂运算时，大于255的值会自动截断为255；
     * 所以，先将图像的灰度值归一化到【0,1】范围，然后再进行幂运算
     * @param image
     */
    public static void transformation_2(Mat image) {

        //定义2个与输入图像大小类型一致的空对象
        Mat dst = new Mat(image.size(),image.type());
        Mat dst_1 = new Mat(image.size(),image.type());
        /*
         * 缩放并转换到另外一种数据类型：
         * dst：目的矩阵；
         * type：需要的输出矩阵类型，或者更明确的，是输出矩阵的深度，如果是负值（常用-1）则输出矩阵和输入矩阵类型相同；
         * scale:比例因子（输入矩阵参数*比例因子）；
         * shift：将输入数组元素按比例缩放后添加的值（第三个参数处理后+第四个参数）；
         * CV_64F:64 -表示双精度 32-表示单精度 F - 浮点  Cx - 通道数,例如RGB就是三通道
         */
        image.convertTo(dst, CvType.CV_64F, 1.0 / 255, 0);

        /*  将每个数组元素提升为幂：
         *  对于非整数幂指数，将使用输入数组元素的绝对值。 但是，可以使用一些额外的操作获得负值的真实值。
         *  对于某些幂值（例如整数值0.5和-0.5），使用了专用的更快算法。
         *  不处理特殊值（NaN，Inf）。
         *  @param 输入数组。
         *  @param 幂的幂指数。
         *  @param 输出数组，其大小和类型与输入数组相同。
         */
        Core.pow(dst, 0.7, dst_1);
        /* 缩放并转换到另外一种数据类型：
         * CV_8UC1---8位无符号的单通道---灰度图片
         * CV_8UC3---8位无符号的三通道---RGB彩色图像
         * CV_8UC4---8位无符号的四通道---带透明色的RGB图像
         */
        dst_1.convertTo(dst_1, CvType.CV_8U,255,0);

        HighGui.imshow("伽马校正", dst_1);
        HighGui.waitKey();
    }

    /**
     * 对数变换可以将图像的低灰度值部分扩展，显示出低灰度部分更多的细节，
     * 将其高灰度值部分压缩，减少高灰度值部分的细节，从而达到强调图像低灰度部分的目的。
     *
     * @param src
     * @return
     */
    public static void logEnhance(Mat src) {
        Mat srcClone = src.clone();
        Mat imageResult = new Mat(srcClone.size(), CvType.CV_32FC3);
        Core.add(srcClone, new Scalar(5, 5, 5), srcClone);
        srcClone.convertTo(srcClone, CvType.CV_32F);
        Core.log(srcClone, imageResult);
//        Core.multiply(imageLog, new Scalar(3,3,3), imageLog);
        Core.normalize(imageResult, imageResult, 0, 255, Core.NORM_MINMAX);
        Core.convertScaleAbs(imageResult, imageResult);
        HighGui.imshow("对数变换", imageResult);
        HighGui.waitKey();
    }

    public static void main(String[] args) {
        Mat src = Imgcodecs.imread("src1.jpg");
        HighGui.imshow("src", src);
        HighGui.waitKey();

        transformation_2(src);

        logEnhance(src);
    }
}
